<template>
	<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
		<a-card :bordered="true" title="基本设置">
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item label="选择主表：" name="dbTable">
						<a-select
							v-model:value="formData.dbTable"
							:filter-option="filterOption"
							:options="tableList"
							placeholder="请选择主表"
							show-search
							style="width: 100%"
							@select="formFieldAssign"
						>
						</a-select>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="表前缀移除：" name="tablePrefix">
						<a-radio-group
							v-model:value="formData.tablePrefix"
							:options="genConst.tablePrefixOptions"
							@change="tablePrefixChange"
						>
						</a-radio-group>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="生成方式：" name="generateType">
						<a-radio-group v-model:value="formData.generateType" :options="genConst.generateTypeOptions">
						</a-radio-group>
					</a-form-item>
				</a-col>
			</a-row>
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item name="moduleType">
						<template #label>
							<a-popover placement="topLeft" title="生成模板说明:">
								<template #content>
									<p>单表:生成普通单表的增删改查</p>
									<p>树表-列表型:生成树型结构的表的增删改查,参考组织管理</p>
									<p>树表-树型:生成树型结构的表的增删改查,参考菜单管理</p>
									<p>主子表:生成主表关联子表的增删改查,删除主表数据会清除相应的子表数据</p>
								</template>
								生成模板:
								<question-circle-outlined />
							</a-popover>
						</template>
						<a-select
							v-model:value="formData.moduleType"
							:options="genConst.moduleTypeOptions"
							placeholder="选择生成模板："
							style="width: 100%"
						>
						</a-select>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="数据权限：" name="dataPermission">
						<a-radio-group
							v-model:value="formData.dataPermission"
							:options="genConst.dataPermissionOptions"
						></a-radio-group>
					</a-form-item>
				</a-col>
				<a-col :span="4">
					<a-form-item label="功能名：" name="functionName">
						<a-input v-model:value="formData.functionName" allow-clear placeholder="请输入功能名" />
					</a-form-item>
				</a-col>
				<a-col :span="4">
					<a-form-item label="后缀：" name="functionNameSuffix">
						<a-input v-model:value="formData.functionNameSuffix" allow-clear placeholder="请输入后缀" />
					</a-form-item>
				</a-col>
			</a-row>
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item label="功能列表：" name="funcList">
						<a-select
							v-model:value="formData.funcList"
							:options="genConst.funcOptions"
							mode="multiple"
							placeholder="请选择功能列表"
							style="width: 100%"
						>
						</a-select>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="作者：" name="authorName">
						<a-input v-model:value="formData.authorName" allow-clear placeholder="请输入作者名" />
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="排序：" name="sortCode">
						<a-slider v-model:value="formData.sortCode" :max="100" style="width: 100%" />
					</a-form-item>
				</a-col>
			</a-row>
			<a-divider v-if="showTree" orientation="left">树表配置</a-divider>
			<a-row v-if="showTree" :gutter="24">
				<a-col :span="8">
					<a-form-item label="树ID字段：" name="treeId">
						<a-select
							v-model:value="formData.treeId"
							:filter-option="filterOption"
							:options="columnOptions"
							placeholder="选择树ID字段："
							show-search
							style="width: 100%"
						/>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="树父ID字段：" name="treePid">
						<a-select
							v-model:value="formData.treePid"
							:filter-option="filterOption"
							:options="columnOptions"
							placeholder="选择树父ID字段："
							show-search
							style="width: 100%"
						/>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="树名称字段：" name="treeName">
						<a-select
							v-model:value="formData.treeName"
							:filter-option="filterOption"
							:options="columnOptions"
							placeholder="选择树名称字段："
							show-search
							style="width: 100%"
						/>
					</a-form-item>
				</a-col>
			</a-row>
			<a-divider v-if="showMaster" orientation="left">主子表配置</a-divider>
			<a-row v-if="showMaster" :gutter="24">
				<a-col :span="8">
					<a-form-item label="关联子表的表名：" name="childTable">
						<a-select
							v-model:value="formData.childTable"
							:filter-option="filterOption"
							:options="childTableList"
							placeholder="选择关联子表的表名："
							show-search
							style="width: 100%"
							@select="selectChildTable"
						/>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="子表关联的外键名：" name="childFk">
						<a-select
							v-model:value="formData.childFk"
							:filter-option="filterOption"
							:options="childColumnOptions"
							placeholder="选择子表关联的外键名："
							show-search
							style="width: 100%"
						/>
					</a-form-item>
				</a-col>
			</a-row>
		</a-card>
		<a-card :bordered="true" style="margin-top: 8px" title="前端设置">
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item label="前端文件夹路径：" name="frontedPath">
						<a-input
							v-model:value="formData.frontedPath"
							allow-clear
							placeholder="前端文件夹路径"
							style="width: calc(100% - 100px)"
						/>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="所属模块：" name="module">
						<a-select
							v-model:value="formData.module"
							:options="moduleOptions"
							placeholder="请选择所属模块"
							style="width: 100%"
							@change="moduleChange(formData.module, false)"
						>
						</a-select>
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="上级目录：" name="menuPid">
						<a-tree-select
							v-model:value="formData.menuPid"
							:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
							:field-names="{
								children: 'children',
								label: 'title',
								value: 'id'
							}"
							:tree-data="menuTreeData"
							allow-clear
							placeholder="请选择上级目录"
							selectable="false"
							style="width: 100%"
							tree-default-expand-all
							tree-line
						></a-tree-select>
					</a-form-item>
				</a-col>
			</a-row>
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item label="表单布局：" name="formLayout">
						<a-radio-group v-model:value="formData.formLayout" :options="genConst.formLayoutOptions" />
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="使用栅格：" name="gridWhether">
						<a-radio-group v-model:value="formData.gridWhether" :options="genConst.gridWhetherOptions" />
					</a-form-item>
				</a-col>
				<a-col :span="8" v-if="formData.moduleType === 'single'">
					<a-form-item label="左侧树：" name="leftTree">
						<a-select
							v-model:value="formData.leftTree"
							:options="genConst.treeOptions"
							placeholder="选择左侧树："
							style="width: 100%"
						>
						</a-select>
						<!--						<a-radio-group v-model:value="formData.leftTree" :options="genConst.treeOptions" />-->
					</a-form-item>
				</a-col>
			</a-row>
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item label="路由名：" name="routeName">
						<a-input v-model:value="formData.routeName" allow-clear placeholder="请输入路由名" />
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="图标：" name="icon">
						<a-input
							v-model:value="formData.icon"
							allow-clear
							placeholder="请选择图标"
							style="width: calc(100% - 100px)"
						/>
						<a-button type="primary" @click="iconSelector.showIconModal(formData.icon)">选择</a-button>
					</a-form-item>
				</a-col>
			</a-row>
		</a-card>
		<a-card :bordered="true" style="margin-top: 8px" title="后端设置">
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item label="业务名：" name="busName">
						<a-input v-model:value="formData.busName" allow-clear placeholder="请输入业务名" />
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="类名：" name="className">
						<a-input v-model:value="formData.className" allow-clear placeholder="请输入类名" />
					</a-form-item>
				</a-col>
				<a-col :span="8">
					<a-form-item label="服务层代码位置：" name="servicePosition">
						<a-select
							v-model:value="formData.servicePosition"
							:filter-option="filterOption"
							:options="servicePositions"
							placeholder="选择服务层代码位置："
							show-search
							style="width: 100%"
						>
						</a-select>
					</a-form-item>
				</a-col>
			</a-row>
			<a-row :gutter="24">
				<a-col :span="8">
					<a-form-item label="接口层代码位置：" name="controllerPosition">
						<a-select
							v-model:value="formData.controllerPosition"
							:filter-option="filterOption"
							:options="controllerPositions"
							placeholder="选择接口层代码位置："
							show-search
							style="width: 100%"
						>
						</a-select>
					</a-form-item>
				</a-col>
			</a-row>
		</a-card>
	</a-form>
	<Icon-selector ref="iconSelector" @iconCallBack="iconCallBack" />
</template>

<script name="genBasic" setup>
	import { required } from '@/utils/formRules'
	import tool from '@/utils/tool'
	import genBasicApi from '@/api/gen/genBasicApi'
	import IconSelector from '@/components/Selector/iconSelector.vue'
	import * as genConst from './genConst'

	const formRef = ref()
	// 表单数据
	const formData = ref({})
	// 定义
	let iconSelector = ref()
	const tableList = ref([])
	const childTableList = ref([]) //子表
	const servicePositions = ref([]) //服务层位置
	const controllerPositions = ref([]) //接口层位置
	const tableColumns = ref([])
	const menuTreeData = ref([])
	const submitLoading = ref(false)
	const moduleOptions = ref()
	const columnOptions = ref()
	const childColumnOptions = ref()

	//显示树表配置
	const showTree = computed(() => {
		return formData.value.moduleType && formData.value.moduleType.includes('tree')
	})

	//显示主子表配置
	const showMaster = computed(() => {
		return formData.value.moduleType && formData.value.moduleType.includes('master')
	})

	// 打开抽屉
	const onOpen = (record) => {
		// 加载默认的模块
		moduleOptions.value = tool.data.get('MENU').map((item) => {
			return {
				label: item.name,
				value: item.id
			}
		})
		//获取程序集
		genBasicApi.basicAssemblies().then((data) => {
			servicePositions.value = data.map((item) => {
				return {
					value: item,
					label: item
				}
			})
			controllerPositions.value = data.map((item) => {
				return {
					value: item,
					label: item
				}
			})
		})
		// 获取数据库中的所有表
		genBasicApi.basicTables().then((data) => {
			tableList.value = data.map((item) => {
				return {
					value: item['tableName'],
					tableName: item['tableName'],
					configId: item['configId'],
					label: `${item['tableDescription']}-${item['configId']}-${item['entityName']}`,
					entityName: item['entityName'],
					tableDescription: item['tableDescription'] || item['entityName'],
					tableColumns: item['columns']
				}
			})
			if (record) {
				formData.value = record
				// 自动填写类名和业务名
				// formFieldAssign(record.dbTable)
				autoModuleType(record) //自动填写模块类型
				// 让模块旁边的上级菜单选中
				moduleChange(record.module, true)
			} else {
				formData.value = {
					sortCode: 99,
					authorName: 'superAdmin',
					tablePrefix: 'Y',
					servicePosition: '',
					controllerPosition: '',
					generateType: 'ZIP',
					routeName: 'biz',
					functionNameSuffix: '管理',
					formLayout: 'vertical',
					gridWhether: 'N',
					leftTree: 'null',
					moduleType: 'single',
					dataPermission: 'N',
					funcList: ['curd']
				}
			}
		})
	}
	// 默认要校验的
	const formRules = {
		tablePrefix: [required('请选择是否移除表前缀')],
		dbTable: [required('请选择主表')],
		dbTableKey: [required('请选择主表主键')],
		generateType: [required('请选择生成方式')],
		module: [required('请选择所属模块')],
		menuPid: [required('请选择上级目录')],
		routeName: [required('请输入路由名')],
		icon: [required('请选择图标')],
		functionName: [required('请输入功能名')],
		busName: [required('请输入业务名')],
		className: [required('请输入类名')],
		frontedPath: [required('请输入前端路径')],
		servicePosition: [required('请输入服务层代码位置')],
		controllerPosition: [required('请输入接口层代码位置')],
		sortCode: [required('请选择排序')],
		formLayout: [required('请选择表单布局')],
		gridWhether: [required('请选择是否使用栅格')],
		authorName: [required('请输入作者名')],
		funcList: [required('请选择功能列表')],
		moduleType: [required('请输入模版类型')],
		dataPermission: [required('请选择数据权限')],
		treeId: [required('请选择树Id字段')],
		treePid: [required('请选择树父Id字段')],
		treeName: [required('请选择树名称字段')],
		childTable: [required('请选择关联子表的表名')],
		childFk: [required('请选择关联子表的外键')]
	}
	// 选择模板的回调
	const moduleChange = (value, assign) => {
		if (!assign) {
			// 先去掉值
			formData.value.menuPid = undefined
		}
		// 加载默认的模块
		const menuTree = tool.data.get('MENU').find((item) => {
			if (item.id === value) {
				return item
			}
		})
		menuTreeData.value = [
			{
				id: '0',
				title: '顶级',
				menuType: 'CATALOG',
				children: traverseChildren(menuTree.children)
			}
		]
	}
	// 遍历增加属性
	const traverseChildren = (data = []) => {
		// 递归遍历控件树
		const traverse = (array) => {
			array.forEach((element) => {
				if (element.menuType === 'CATALOG') {
					if (element.children) {
						traverse(element.children)
					}
				} else {
					// 设置不可用
					element.disabled = true
					element.selectable = false
				}
			})
		}
		traverse(data)
		return data
	}

	// 点击选择是否移除前缀
	const tablePrefixChange = () => {
		const tableName = formData.value.dbTable
		if (tableName) {
			const tableNameHump = getTableNameToHump(tableName)
			formData.value.busName = tableNameHump.toLowerCase()
		}
	}
	// 表单内设置默认的值
	const formFieldAssign = (value, options) => {
		const tableNameHump = getTableNameToHump(options.tableName)
		formData.value.busName = tableNameHump.toLowerCase()
		formData.value.className = getClassName(options.tableName)
		formData.value.entityName = options.entityName
		formData.value.configId = options.configId
		columnOptions.value = options.tableColumns.map((item) => {
			return {
				value: item['columnName'],
				label: `${item['columnName']}:${item['columnDescription']}`
			}
		})
		childTableList.value = tableList.value.filter((item) => {
			return item.configId == options.configId
		})
	}
	// 生成模版字段填充
	const autoModuleType = (record) => {
		//获取表信息
		let table = tableList.value.find((item) => {
			return item.tableName === record.dbTable && item.configId == record.configId
		})
		//树ID列表
		columnOptions.value = table.tableColumns.map((item) => {
			return {
				value: item['columnName'],
				label: `${item['columnName']}:${item['columnDescription']}`
			}
		})
		//获取子表列表
		childTableList.value = tableList.value.filter((item) => item.configId == table.configId)
		//获取子表信息
		let subTable = childTableList.value.find((item) => {
			return item.tableName === record.childTable && item.configId == record.configId
		})
		if (subTable) {
			//获取子表字段
			childColumnOptions.value = subTable.tableColumns.map((item) => {
				return {
					value: item['columnName'],
					label: `${item['columnName']}:${item['columnDescription']}`
				}
			})
		}
	}

	//选择子表
	const selectChildTable = (value, options) => {
		formData.value.childTable = options.entityName //子表名实体赋值
		childColumnOptions.value = options.tableColumns.map((item) => {
			return {
				value: item['columnName'],
				label: `${item['columnName']}-${item['columnDescription']}`
			}
		})
	}

	// 获取数据库表的驼峰命名
	const getTableNameToHump = (tableName) => {
		if (tableName) {
			const arr = tableName.toLowerCase().split('_')
			if (formData.value.tablePrefix === 'Y') {
				arr.splice(0, 1)
			}
			for (let i = 0; i < arr.length; i++) {
				// charAt()方法得到第一个字母，slice()得到第二个字母以后的字符串
				arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1)
			}
			return arr.join('')
		}
		return ''
	}
	// 获取数据库表的驼峰命名
	const getClassName = (tableName) => {
		if (tableName) {
			const arr = tableName.toLowerCase().split('_')
			for (let i = 0; i < arr.length; i++) {
				// charAt()方法得到第一个字母，slice()得到第二个字母以后的字符串
				arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1)
			}
			return arr.join('')
		}
		return ''
	}

	// 验证并提交数据
	const onSubmit = () => {
		return new Promise((resolve, reject) => {
			formRef.value
				.validate()
				.then(() => {
					submitLoading.value = true
					genBasicApi
						.submitForm(formData.value, formData.value.id)
						.then((data) => {
							resolve(data)
						})
						.finally(() => {
							submitLoading.value = false
						})
				})
				.catch((err) => {
					reject(err)
				})
		})
	}
	// 图标选择器回调
	const iconCallBack = (value) => {
		formData.value.icon = value
	}

	// 下拉框回调
	const filterOption = (input, option) => {
		return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
	}

	// 调用这个函数将子组件的一些数据和方法暴露出去
	defineExpose({
		onOpen,
		onSubmit
	})
</script>
<style scoped>
	.childAddButton {
		margin-bottom: 10px;
	}

	.form-row {
		background-color: var(--item-hover-bg);
		margin-left: 0px !important;
	}

	.form-row-con {
		padding-bottom: 5px;
		padding-top: 5px;
		padding-left: 15px;
	}

	.form-div {
		padding-top: 10px;
	}
</style>
